package com.fjwt.gz.components.oss.ctrl;

import cn.hutool.core.lang.UUID;
import com.fjwt.gz.components.oss.model.OssFileConfig;
import com.fjwt.gz.components.oss.service.IOssService;
import com.fjwt.gz.core.constants.ApiCodeEnum;
import com.fjwt.gz.core.ctrls.AbstractCtrl;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.core.model.ApiRes;
import com.fjwt.gz.core.model.DBOSSConfig;
import com.fjwt.gz.core.service.ISysConfigService;
import com.fjwt.gz.core.utils.FileKit;
import com.fjwt.gz.core.utils.SpringBeansUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/*
 * 统一文件上传接口（ossFile）
 *
 * @author wg
 * @site https://pt.jdyd.xyz/
 * @date 2021/6/8 17:07
 */
@RestController
@RequestMapping("/api/ossFiles")
public class OssFileController extends AbstractCtrl {
    @Value("${province.code}")
    private String provinceCode;


    @Autowired
    private ISysConfigService sysConfigService;

    /**
     * 文件上传、 将二进制文件上传到服务器， 在保存到对应是oss上。 （单文件）
     */
    @PostMapping("/singleFile")
    public ApiRes singleFileUpload(@RequestParam("file") MultipartFile file) {

        if (file == null) {
            return ApiRes.fail(ApiCodeEnum.SYSTEM_ERROR, "选择文件不存在");
        }
        try {

            // 获取业务类型
            String bizType = getValStringRequired("bizType");

            // 文件存储路径
            String saveDirAndFileName = commonCheckAndGetFilePath(provinceCode, bizType, file.getOriginalFilename(), file.getSize());
            String fileName = saveDirAndFileName;
            // 预览地址
            String url = getOssService().upload2PreviewUrl(OssFileConfig.getOssFileConfigByBizType(bizType).getOssSavePlaceEnum(), file, fileName);
            String data = url;
            return ApiRes.ok(data);
        } catch (BizException biz) {
            throw biz;
        } catch (Exception e) {
            logger.error("upload error, fileName = {}", file.getOriginalFilename(), e);
            throw new BizException(ApiCodeEnum.SYSTEM_ERROR);
        }
    }


    /**
     * 获取文件的上传form表单参数， 文件不上传到服务器， 返回form直接上传到对应的oss地址。
     */
    @PostMapping("/form")
    public ApiRes formParams() {
        String bizType = getValStringRequired("bizType"); // 获取文件上传类型

        String sourceFileName = getValStringRequired("sourceFileName");  //用户上传的原始文件名称
        Long sourceFileSize = getValLongRequired("sourceFileSize");  //用户上传的原始文件大小 单位： 字节Byte

        // 文件存储路径
        String saveDirAndFileName = commonCheckAndGetFilePath(provinceCode, bizType, sourceFileName, sourceFileSize);

        OssFileConfig ossFileConfig = OssFileConfig.getOssFileConfigByBizType(bizType);

        IOssService.UploadFormParams result = getOssService().genFormParams(bizType, ossFileConfig, saveDirAndFileName);
        return ApiRes.ok(result);
    }

    /**
     * 统一校验, 获取文件的存储地址
     */
    private String commonCheckAndGetFilePath(String provinceCode, String bizType, String fileOriginalFilename, Long fileSize) {

        OssFileConfig ossFileConfig = OssFileConfig.getOssFileConfigByBizType(bizType);

        //1. 判断bizType 是否可用
        if (ossFileConfig == null) {
            throw new BizException("类型有误");
        }

        // 2. 判断文件是否支持
        String fileSuffix = FileKit.getFileSuffix(fileOriginalFilename, false);
        if (!ossFileConfig.isAllowFileSuffix(fileSuffix)) {
            throw new BizException("上传文件格式不支持！");
        }

        // 3. 判断文件大小是否超限
        if (!ossFileConfig.isMaxSizeLimit(fileSize)) {
            throw new BizException("上传大小请限制在[" + ossFileConfig.getMaxSize() / 1024 / 1024 + "M]以内！");
        }

        // 新文件地址 (xxx/xxx.jpg 格式)
        return provinceCode + "/" + bizType + "/" + UUID.fastUUID() + "." + fileSuffix;
    }


    /**
     * 后端java直接调用上传
     */
    public String singleFileUpload(MultipartFile file, String bizType) {

        // 文件存储路径
        String saveDirAndFileName = commonCheckAndGetFilePath(provinceCode, bizType, file.getOriginalFilename(), file.getSize());

        // 预览地址
        return getOssService().upload2PreviewUrl(OssFileConfig.getOssFileConfigByBizType(bizType).getOssSavePlaceEnum(), file, saveDirAndFileName);

    }


    private IOssService getOssService() {

        DBOSSConfig dbossConfig = sysConfigService.getOssConfig();
        return SpringBeansUtil.getBean(dbossConfig.getOssUseType() + "OssService", IOssService.class);

    }


}
